package org.toves.checklua.ast;

import java.util.Iterator;
import java.util.NoSuchElementException;

class AstChildren implements Iterator<AstNode>, Iterable<AstNode> {
	private AstNode node;
	private int inext; // index of parameter
	private int jnext; // index within parameter (if parameter is an array -
						// otherwise jnext is irrelevant)
	
	AstChildren(AstNode node) {
		this.node = node;
		inext = -1; // for the moment set it to be just before the first parm
		jnext = 0;
		advance(); // and now advance it to the first parameter
	}
	
	public boolean hasNext() {
		return inext < node.getParameterCount();
	}
	
	public AstNode next() {
		if (!hasNext()) {
			throw new NoSuchElementException();
		}
		
		int i = inext;
		int j = jnext;
		
		Object parm = node.getParameter(i);
		if (parm instanceof AstNode) {
			advance();
			return (AstNode) parm;
		} else if (parm instanceof AstNode[]) {
			AstNode[] parms = (AstNode[]) parm;
			if (j < parms.length) {
				if (j + 1 < parms.length) {
					jnext = j + 1;
				} else {
					advance();
				}
				return parms[j];
			} else { // this should never happen
				advance();
				return null;
			}
		} else { // this should never happen
			advance();
			return null;
		}
	}
	
	private void advance() {
		int i = inext;
		do {
			i++;
		} while (i < node.getParameterCount() && !parmHasChild(i));
		inext = i;
		jnext = 0;
	}
	
	private boolean parmHasChild(int index) {
		Object parm = node.getParameter(index);
		if (parm instanceof AstNode) return true;
		if (parm instanceof AstNode[]) return ((AstNode[]) parm).length > 0;
		return false;
	}
	
	public void remove() {
		throw new UnsupportedOperationException("cannot remove children");
	}

	public Iterator<AstNode> iterator() {
		return this;
	}
}
